<?php
/**
 * @file cache.class.php
 * @author 禅元天道 chanyuantiandao@126.com
 * @DateTime 2022-01-22 13:03
 * @brief TODO
 */

!defined('CHAN_CMS') && exit('非法访问！');

class Cache
{
    private static $_instance = null;
    private $config = array();

    const SQL = 1;
    const PHP = 2;
    const HTML = 3;
    private $md5Length = 12;

    public static function getInstance($config)
    {
        if(is_null(self::$_instance) || !self::$_instance instanceof self){
            self::$_instance = new self($config);
        }
        return self::$_instance;
    }

    private function __construct($config){
        $this->config = $config;

        $isDirExists = true;
        foreach (array(self::SQL, self::PHP, self::HTML) as $dir){
            $cachePath = FileHelper::joinPathWithRoot($this->config['path'], getmd5($dir, $this->md5Length));
            if(!is_dir($cachePath) && !mkdir($cachePath, 0666, true)){
                $isDirExists = false;
                break;
            }
        }
        if(!$isDirExists){
            throw new ChanException('创建缓存目录'.$cachePath.'失败！');
        }
    }

    public function getPath(string $key, int $type = self::SQL){
        return FileHelper::joinPathWithRoot($this->config['path'], getmd5($type, $this->md5Length)).getMd5($key).'.php';
    }

    public function set(string $key, string $data, int $type = self::SQL){
        if($this->config['expire_time'] > 0){
            $cacheFile = $this->getPath($key, $type);
            $data = App::config('site/noAccessHeader').'<?php $cacheReturn = \''.$data.'\'; ?>';
            if(!file_put_contents($cacheFile, $data)){
                return false;
            }else{
                return true;
            }
        }else{
            return false;
        }
    }

    public function get($key, $type = self::SQL){
        if($this->config['expire_time'] > 0){
            $cacheFile = $this->getPath($key, $type);
            if(file_exists($cacheFile) && (time() - filemtime($cacheFile) < $this->config['expire_time'])){
                require_once $cacheFile;
                if(isset($cacheReturn)){
                    return $cacheReturn;
                }else{
                    return null;
                }
            }else{
                return null;
            }
        }else{
            return null;
        }
    }


    public function remove($key = '', $type = self::SQL){
        $cacheFile = $this->getPath($key, $type);
        if(is_file($cacheFile)){
            return unlink($cacheFile);
        }else{
            return true;
        }
    }


    public function removeAll($flag = '', $type = self::SQL){
        $cachePath = FileHelper::joinPathWithRoot($this->config['path'], getmd5($type, $this->md5Length));
        $list = scandir($cachePath);
        $result = true;
        foreach ($list as $name) {
            if(strpos($name, $flag) === 0){
                $cacheName = $cachePath.$name;
                if(is_file($cacheName)){
                    if(!unlink($cacheName)){
                        $result = false;
                        break;
                    }
                }
            }
        }
        return $result;
    }

    private function __clone(){}

    function __destruct() {
    }
}